/*
 * StringTokenizer.hpp
 *
 *  Created on: 4 juin 2014
 *      Author: Raphaël
 */

#ifndef STRINGTOKENIZER_HPP_
#define STRINGTOKENIZER_HPP_

#include <vector>
#include <string>

namespace ch
{
namespace raph
{
namespace tools
{

class StringTokenizer
    {
    private:
    typedef signed long long int integer;
    struct DefaultAccessor
        {
        const char& operator()(const char& xValue) const noexcept
            {
            return xValue;
            }
        };
    std::vector<std::string> m_elements;
    std::string m_str;

    public:
    typedef std::vector<std::string>::const_iterator const_iterator;
    typedef std::vector<std::string>::const_reverse_iterator const_reverse_iterator;
    StringTokenizer();
    virtual ~StringTokenizer();
    template<typename InputIterator, class InputAccessor = DefaultAccessor>
    void operator()(
            InputIterator xInputBegin,
            const InputIterator& xInputEnd,
            const std::string& xDelim,
            const InputAccessor& xInputAccessor = InputAccessor());
    StringTokenizer::const_iterator cbegin();
    StringTokenizer::const_iterator cend();
    StringTokenizer::const_reverse_iterator crbegin();
    StringTokenizer::const_reverse_iterator crend();
    };

template<typename InputIterator, class InputAccessor>
void StringTokenizer::operator()(
        InputIterator xInputBegin,
        const InputIterator& xInputEnd,
        const std::string& xDelim,
        const InputAccessor& xInputAccessor)
    {
    m_str.clear();
    m_elements.clear();
    for (; xInputBegin != xInputEnd; ++xInputBegin)
        {
        m_str.insert(m_str.end(), xInputAccessor(*xInputBegin));
        }
    if (m_str.find(xDelim) != std::string::npos)
        {
        m_str.append(xDelim);
        }
    const integer size = m_str.size();
    integer pos = -1;
    while (pos != size)
        {
        integer last = m_str.find(xDelim, ++pos);
        if (last != std::string::npos)
            {
            m_elements.push_back(m_str.substr(pos, last - pos));
            pos = last;
            }
        }
    }

} /* namespace tools */
} /* namespace raph */
} /* namespace ch */

#endif /* STRINGTOKENIZER_HPP_ */
